package com.fast.develop.integration.orm;

import cn.hutool.core.bean.BeanUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;

import javax.persistence.metamodel.EntityType;
import java.io.Serializable;
import java.util.Map;

/**
 * @author 莫寅
 * @createTime 2022-06-23 03:11
 * @desc：
 */
public class HibernateDomainModelSessionManager extends AbstractDomainModelSessionManager {

    private Session session;
    private Map<String, EntityType> entityTypes;

    public HibernateDomainModelSessionManager(Session session, Map<String, EntityType> entityTypes) {
        super(session);
        this.session = session;
        this.entityTypes = entityTypes;
    }


    private Object convertMetaModelType(String model, Object object){
        if(object instanceof Map){
            return BeanUtil.toBean(object, entityTypes.get(model).getJavaType());
        }else{
            return object;
        }
    }



    @Override
    public Serializable create(String model, Object object){

        Object data = convertMetaModelType(model, object);

        Transaction transaction = session.beginTransaction();
        try{
            Serializable serializable = session.save(model, data);

            transaction.commit();
            return serializable;
        }catch (Exception e){
            transaction.rollback();
            throw e;
        }
    }

    /**
     * hibernate 更新
     * 注意一：当传入object为map时，hibernate metaModel为class无法更新，需要转成class才能保存
     * 注意二：当直接修改时如没有值为null也会对数据库表进行修改为null，为了避免将数据库值被修改需要先查询之后再修改
     * 注意三：当查询后的对像实例为：11001，将copy成另一个对象实例后也无法修改，需要将原对象实例进行保存
     * @param model
     * @param id
     * @param object
     */
    @Override
    public void update(String model, Serializable id, Object object){
        Object data = convertMetaModelType(model, object);

        Transaction transaction = session.beginTransaction();
        try{
            Object obj = session.get(model, id);
            Map mergeData = BeanUtil.beanToMap(data, BeanUtil.beanToMap(obj), false, true);

            BeanUtil.copyProperties(convertMetaModelType(model, mergeData), obj);
            session.update(model, obj);

            transaction.commit();
        }catch (Exception e){
            transaction.rollback();
            throw e;
        }
    }


    @Override
    protected String idName(String meta){
        return "id";
//        entityTypes.get(meta).
//        return metaDomainModelsVisit.getIdentifierProperty(meta).getName();
    }

}
